/*
 * @Description:类的多态
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-04-29 13:50:36
 * @LastEditTime: 2021-04-30 15:18:28
 */

/**
 * 在ts中父类的引用指向子类的对象
 * TS的不同子类针对相同的方法，产生了不同的行为。
 * 父类定义一个方法不去实现，让继承他的子类去实现。每一个子类都又不同的表现
 * TS中多态是属于继承的，是由继承产生的。
 * Ts实现接口，可以实现多个，用逗号分割`class A extends B implements C,D,E`
 */

interface iAnimal {
    type: string
    name: string
    eat(food: string): void
}

/* 实现了iAnimal接口的父类 */
class Animal implements iAnimal {
    type
    name
    constructor(type: string, name: string) {
        this.type = type
        this.name = name
    }
    eat(food: string) {
        const { type, name } = this
        console.log(`${type + name}喜欢吃${food}`)
    }
}

/* 子类1实现多态 */
class Cat extends Animal {
    eat(food: string) {
        const { type, name } = this
        console.log(`${type + name}正在吃${food}`)
    }
    play() {
        const { type, name } = this
        console.log(`${type + name}在玩耍`)
    }
}

/* 子类2实现多态 */
class Dog extends Animal {
    eat(food: string) {
        const { type, name } = this
        console.log(`${type + name}吃${food}很香`)
    }
}

let cat = new Cat("小猫", "喵喵")
cat.eat("鱼")   // 小猫喵喵正在吃鱼

let cat2: Cat = new Cat("小猫", "喵喵")
cat2.eat("鱼")   // 小猫喵喵正在吃鱼
cat2.play()   // 小猫喵喵在玩耍


/**
 * 不同子类的方法，同样属于父类类型
 */
let cat3: Animal = new Cat("小猫", "喵喵")
cat3.eat("鱼")   // 小猫喵喵正在吃鱼
// cat3.play()   // 报错：类型“Animal”上不存在属性“play”。

// let cat3: Cat = new Animal("小狗", "汪汪")  // 报错：类型 "Animal" 中缺少属性 "play"，但类型 "Cat" 中需要该属性。


let dog: Animal = new Dog("小狗", "汪汪")
dog.eat("肉")   // 小狗汪汪吃肉很香